package org.kazuhiko.rpg.objects;

import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_FRONT;
import static org.lwjgl.opengl.GL11.GL_NORMAL_ARRAY;
import static org.lwjgl.opengl.GL11.GL_SHININESS;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.GL_VERTEX_ARRAY;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glDisableClientState;
import static org.lwjgl.opengl.GL11.glDrawArrays;
import static org.lwjgl.opengl.GL11.glEnableClientState;
import static org.lwjgl.opengl.GL11.glMaterialf;
import static org.lwjgl.opengl.GL11.glNormalPointer;
import static org.lwjgl.opengl.GL11.glRotatef;
import static org.lwjgl.opengl.GL11.glTranslatef;
import static org.lwjgl.opengl.GL11.glVertexPointer;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.glBindBuffer;

import org.kazuhiko.rpg.core.Drawable;
import org.kazuhiko.rpg.core.Physics;
import org.kazuhiko.rpg.core.Physics.GravityAcceleration;
import org.lwjgl.util.vector.Vector3f;

public class Cube extends Drawable
{
	public enum CubeType
	{
		GRASS( 0.30f, 2.55f, 0f ),
		DIRT( 1.16f, 0.74f, 0.44f ),
		WATER( 0.20f, 1.86f, 2.34f),
		STONE( 1.13f, 1.13f, 1.13f ),
		LAVA( 2.38f, 1.36f, 0.36f );
		
		CubeType( float red, float green, float blue )
		{
			this.red = red;
			this.green = green;
			this.blue = blue;
		}
		
		public float red;
		public float green;
		public float blue;
	}
	
	//The color of the cube
	private CubeType cubeType = CubeType.DIRT;
	
	//The constructor
	public Cube()
	{
		//Giving the path to the model
		super( "res/models/cube.obj", true );
	}
	
	//Setting the type for different colors
	public void setType( CubeType type )
	{
		this.cubeType = type;
	}
	
	//Rendering the cube
	public void render()
	{
		//Set position
		glTranslatef( getPosition().x, getPosition().y, getPosition().z );
		
		glRotatef( getRotation().x, 1, 0, 0 );
		glRotatef( getRotation().y, 0, 1, 0 );
		glRotatef( getRotation().z, 0, 0, 1 );
		
		//Vertex handle
		glBindBuffer( GL_ARRAY_BUFFER, getVertexHandle() );
		glVertexPointer(3, GL_FLOAT, 0, 0L);
		
		//Normal handle
        glBindBuffer(GL_ARRAY_BUFFER, getNormalHandle() );
        glNormalPointer(GL_FLOAT, 0, 0L);
        
        //Enable states
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        
        //Setting the color
        glColor3f( cubeType.red, cubeType.green, cubeType.blue );
        //Setting the material
        glMaterialf(GL_FRONT, GL_SHININESS, 20f);
        //Drawing the model
        glDrawArrays(GL_TRIANGLES, 0, getModel().faces.size() * 3);
        
        //Disable states
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
        
        //Reset position
        glTranslatef( -getPosition().x, -getPosition().y, -getPosition().z );
        
        glRotatef( -getRotation().x, 1, 0, 0 );
		glRotatef( -getRotation().y, 0, 1, 0 );
		glRotatef( -getRotation().z, 0, 0, 1 );
	}

	@Override
	public void tick()
	{
		if( !colliding() )
		{
			if( getFallingtime() <= 0 )
			{
				setStartFallingHeight( getPosition().y );
			}
			
			setPosition( new Vector3f( getPosition().x, getStartFallingHeight() - ( (float) ( getFallingtime() * Physics.getWeight( getMass(), GravityAcceleration.EARTH ) * 0.01 ) ), getPosition().z ) );
			
			setFallingTime( getFallingtime() + 1 );
		}
		
		if( getPosition().y < 0 )
		{
			setPosition( new Vector3f( getPosition().x, 0, getPosition().z ) );
		}
	}
}
